package com.reformer.commons.utils;

import com.reformer.commons.constant.RsaSignatureAlgorithm;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure;

import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

@Deprecated
public class RsaUtils {
    //将base64编码后的公钥字符串转成PublicKey实例

    /*
    todo
     */
    private static PublicKey getPkcs1PublicKey(String publicKey) throws Exception {
//        RSAPublicKeyStructure rsaPublicKeyStructure = new RSAPublicKeyStructure((ASN1Sequence) ASN1Sequence.fromByteArray(Base64.getDecoder().decode(publicKey)));
//        RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(rsaPublicKeyStructure.getModulus(), rsaPublicKeyStructure.getPublicExponent());
//        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//        return keyFactory.generatePublic(rsaPublicKeySpec);
        return null;
    }

    private static PublicKey getPkcs8PublicKey(String publicKey) throws Exception {
//        byte[] keyBytes = Base64.getDecoder().decode(publicKey.getBytes("UTF-8"));
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(keySpec);
    }

    //将base64编码后的私钥字符串转成PrivateKey实例
    private static PrivateKey getPkcs1PrivateKey(String privateKey) throws Exception {
        RSAPrivateKeyStructure asn1PrivKey = new RSAPrivateKeyStructure((ASN1Sequence) ASN1Sequence.fromByteArray(Base64.getDecoder().decode(privateKey)));
        RSAPrivateKeySpec rsaPrivKeySpec = new RSAPrivateKeySpec(asn1PrivKey.getModulus(), asn1PrivKey.getPrivateExponent());
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(rsaPrivKeySpec);
    }

    private static PrivateKey getPkcs8PrivateKey(String privateKey) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(privateKey.getBytes());
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    }

    //公钥加密
    public static String encrypt(String plainText, String publicKeyString) throws Exception {
        return encrypt(plainText, getPkcs8PublicKey(trim(publicKeyString)));
    }

    public static String encryptByPkcs1(String plainText, String publicKeyString) throws Exception {
        return encrypt(plainText, getPkcs8PublicKey(trim(publicKeyString)));
    }

    private static String encrypt(String plainText, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");//java默认"RSA"="RSA/ECB/PKCS1Padding"
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return Base64.getEncoder().encodeToString(cipher.doFinal(plainText.getBytes("UTF-8")));
    }

    //私钥解密
    public static String decrypt(String cipherText, String privateKeyString) throws Exception {
        return decrypt(cipherText, getPkcs8PrivateKey(trim(privateKeyString)));
    }

    public static String decryptByPkcs1(String cipherText, String privateKeyString) throws Exception {
        return decrypt(cipherText, getPkcs1PrivateKey(trim(privateKeyString)));
    }

    private static String decrypt(String cipherText, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return new String(cipher.doFinal(Base64.getDecoder().decode(cipherText)), "UTF-8");
    }

    /**
     * pkcs8格式的私钥
     * @param plainText
     * @param privateKeyString
     * @return
     * @throws Exception
     */
    public static String getSignature(String plainText, String privateKeyString) throws Exception {
        return getSignature(plainText, getPkcs8PrivateKey(trim(privateKeyString)));
    }

    /**
     * pkcs1格式的私钥
     * @param plainText
     * @param privateKeyString
     * @return
     * @throws Exception
     */
    public static String getSignatureByPkcs1(String plainText, String privateKeyString) throws Exception {
        return getSignature(plainText, getPkcs1PrivateKey(trim(privateKeyString)));
    }

    /**
     * pkcs8 验签
     * @param plainText
     * @param sign
     * @param publicKeyString
     * @return
     * @throws Exception
     */
    public static boolean verify(String plainText, String sign, String publicKeyString) throws Exception {
        return verify(plainText, sign, getPkcs8PublicKey(trim(publicKeyString)));
    }

    public static boolean verifyByPkcs1(String plainText, String sign, String publicKeyString) throws Exception {
        return verify(plainText, sign, getPkcs1PublicKey(trim(publicKeyString)));
    }

    private static boolean verify(String plainText, String sign, PublicKey publicKey) throws Exception {
        Signature signature = Signature.getInstance(RsaSignatureAlgorithm.SHA1WithRSA.getAltorithm());
        signature.initVerify(publicKey);
        signature.update(plainText.getBytes("UTF-8"));
        return signature.verify(Base64.getDecoder().decode(sign.getBytes()));
    }

    private static String getSignature(String plainText, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance(RsaSignatureAlgorithm.SHA1WithRSA.getAltorithm());
        signature.initSign(privateKey);
        signature.update(plainText.getBytes("UTF-8"));
        return Base64.getEncoder().encodeToString(signature.sign());
    }

    /**
     * 处理公钥私钥格式，去掉原始的首位行和换行
     * @param key
     * @return
     */
    public static String trim(String key){
        if (key == null) {
            throw new IllegalArgumentException("RSA密钥不能为空");
        }
        if (key.startsWith("-----BEGIN RSA PRIVATE KEY-----")) {//私钥
            key = key.replace("-----BEGIN RSA PRIVATE KEY-----", "");
            key = key.replace("-----END RSA PRIVATE KEY-----", "");
            key = key.replaceAll("\r|\n|\r\n", "");
            return key;
        }
        if (key.startsWith("-----BEGIN RSA PUBLIC KEY-----")) {//私钥
            key = key.replace("-----BEGIN RSA PRIVATE KEY-----", "");
            key = key.replace("-----END RSA PUBLIC KEY-----", "");
            key = key.replaceAll("\r|\n|\r\n", "");
            return key;
        }
        return key;
    }

}